﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Xaml;
using UIT.Controls.Containers;
using System.Xml;
using System.Web.Compilation;
using System.Reflection;
using JQueryControlToolkit;
using System.Collections;
using System.IO;
using System.Net;
using System.Resources;

namespace UIT.Web
{
	public class PageHandlerFactory : IHttpHandlerFactory
	{
		private static bool initialized;

		public static void EnsureExecutingAssemblyInitialized()
		{
			if (initialized)
				return;
			initialized = true;
			if (GetExecutingAssembly != null)
				ExecutingAssembly = GetExecutingAssembly();
		}

		public static event Func<Assembly> GetExecutingAssembly;

		public static Assembly ExecutingAssembly { get; internal set; }

		#region IHttpHandlerFactory Members

		public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
		{
			return new PageHandler();
		}

		public void ReleaseHandler(IHttpHandler handler)
		{
		}

		#endregion
	}


	public class PageHandler : IHttpHandler
	{
		static PageHandler()
		{
			PageHandlerFactory.EnsureExecutingAssemblyInitialized();
			references = new List<Assembly>();
			if (PageHandlerFactory.ExecutingAssembly != null)
				references.Add(PageHandlerFactory.ExecutingAssembly);

			foreach (Assembly assembly in BuildManager.GetReferencedAssemblies())
				references.Add(assembly);
		}

		#region IHttpHandler Members

		public bool IsReusable
		{
			get { return true; }
		}

		internal static List<Assembly> references;

		public void ProcessRequest(HttpContext context)
		{
			WebRendererManager.EnsureInitialized();
			Uri uri;
			if (PageHandlerFactory.ExecutingAssembly != null)
				uri = new Uri("application://" + PageHandlerFactory.ExecutingAssembly.GetName().Name + context.Request.AppRelativeCurrentExecutionFilePath.Substring(1));
			else
				uri = new Uri("file://" + context.Request.PhysicalPath.Substring(0, context.Request.PhysicalPath.Length - 1));

			using (Stream pageStream = UIT.Application.GetResourceStream(uri))
			{
				using (Page p = RendererManager.CreateInstance<Page>(pageStream))
				{
					ApplyPostBackValuesIfPossible(context, p);
					RaiseEvents(context, p);
					ExecuteCommand(context, p);
					context.Response.HeaderEncoding = Encoding.UTF8;
					if (context.Request.HttpMethod == "GET")
					{
						var writer = XmlWriter.Create(context.Response.Output, new XmlWriterSettings() { OmitXmlDeclaration = true });
						WebRendererManager.Render(p, writer);
						writer.Flush();
					}
					else
					{
						context.Response.StatusCode = 200;
						context.Response.ContentType = "text/javascript";
						foreach (DictionaryEntry item in context.Items)
						{
							DomResult js = item.Value as DomResult;
							if (js != null)
								js.ToScript(context.Response.Output);
						}
						foreach (DomResult js in ScriptManager.RegisteredScripts.Values)
						{
							if (js != null)
								js.ToScript(context.Response.Output);
						}
						context.Response.Output.Flush();
					}
				}
				pageStream.Close();
				pageStream.Dispose();
			}
		}

		private void ExecuteCommand(HttpContext context, Page p)
		{
			if (context.Request.HttpMethod != "GET")
			{

			}
		}

		private void RaiseEvents(HttpContext context, Page p)
		{
			if (context.Request.HttpMethod != "GET")
			{
				var postBack = new EventRaiserVisitor(context);
				postBack.Visit(p);
			}
		}

		private void ApplyPostBackValuesIfPossible(HttpContext context, Page p)
		{
			if (context.Request.HttpMethod != "GET")
			{
				var postBack = new PostBackValueVisitor(context);
                postBack.Visit(p);
			}
		}

		#endregion
	}
}
